Challenge: Mystery Word Puzzle

Limbic Region on 2005-01-12T18:38:58

See http://www.perlmonks.org/index.pl?node_id=421692> for details. Basically it is one of those things that seems easy to do by hand but not as easy to translate to code. Feel free to reply here or there or not at all ;-)
Cheers L~R


an approach

jmm on 2005-01-12T20:48:09

I'd use some simple building blocks. sig(word) would return a hash, keyed by letters, counting the number of times that letter occurred in the word. sigintersect( sig1, sig2 ) would take two such signiatures and count the number of overlap letters. Keep an array of hint info: for each hint record the word, the number of total matches, and the sig for that word. To test a word from the dictionary, you first get its sig. Then, for each hint, check whether sigintersect( word sig, hint sig ) equals the hint's number. Skip the word at the first mismatch. Here's some code (written directly into this reply and not tested to even be syntactically valid :-).
sub sig {
    my $word = shift;
    my $sig = {};

    ++$sig->{$_} for split //, $word;
    return $sig;
}

sub sigintersect {
    my( $sig1, $sig2 ) = @_;
    my $count = 0;

    $count += min( $sig1->{$_}, $sig2->{$_} ) for keys %$sig1;
    return $count;
}

my @hints;

sub addhint {
    my( $word, $count ) = @_;
    push @hints, [ $word, $count, sig($word) ];
}

sub checkdictword {
    my $word = shift;
    my $sig = sig($word);

    foreach my $hint (@hints) {
        my( $hword, $hcount, $hsig ) = @$hint;
        return undef unless $hcount == sigintersect( $sig, $hsig );
    }
    return $word;
}